using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Windows.Forms.DataVisualization.Charting;
using Chadsoft.CTools.Models;
using OpenTK;
using Tao.OpenGl;
using System.Globalization;
using MKDS_Course_Editor.KCL;
using System.Collections.ObjectModel;
using System.Windows.Forms.ComponentModel;
using System.Collections;
using System.Threading;

namespace MKDS_Course_Editor
{
    public partial class kcl : Form
    {
        List<float> vx = new List<float>();
        List<float> vy = new List<float>();
        List<float> vz = new List<float>();
        bool preview = false;
        public static Stream path_ = null;
        public string path = "";
        public kcl(string path)
        {

            InitializeComponent();
            this.path = path;
            path_ = new MemoryStream(File.ReadAllBytes(path));
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        public kcl(Stream path, bool str)
        {

            InitializeComponent();
            path_ = path;
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        public kcl(List<float> vx, List<float> vy, List<float> vz)
        {

            InitializeComponent();
            preview = true;
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        void simpleOpenGlControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            dist += (float)e.Delta / 1000;
            simpleOpenGlControl1.Invalidate();
            RenderFunc1();
        }
        float cubesize = 0;
        private void kcl_Load(object sender, EventArgs e)
        {
            //int gcd = GCD(Width, Height);

            //Gl.glFrustum(-(Width / gcd), (Width / gcd), -(Height / gcd), (Height / gcd), 0, 0);  // apply the projection matrix
            /* if (preview == false)
             {
                 nkm_file.kcl kcl = new nkm_file.kcl();
                 BinaryReader br = new BinaryReader(path_);
                 kcl.HEADER.first = parselittle(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.second = parselittle(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.thirt = parselittle(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.last = parselittle(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.unknown1 = parselittle(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Spatial_grid_X = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 64000;
                 kcl.HEADER.Spatial_grid_Y = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 64000;
                 kcl.HEADER.Spatial_grid_Z = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 64000;
                 kcl.HEADER.X_Mask = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Y_Mask = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Z_Mask = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Coordinate_shift = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Y_shift = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));
                 kcl.HEADER.Z_shift = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", ""));

                 int nodes = (((~(int)kcl.HEADER.X_Mask >> (int)kcl.HEADER.Coordinate_shift) + 1) * ((~(int)kcl.HEADER.Y_Mask >> (int)kcl.HEADER.Coordinate_shift) + 1)) * ((~(int)kcl.HEADER.Z_Mask >> (int)kcl.HEADER.Coordinate_shift) + 1);
                 br.ReadBytes(kcl.HEADER.first - 56);
                 kcl.section1.count = kcl.HEADER.second - kcl.HEADER.first;
                 kcl.section2.count = (kcl.HEADER.thirt + 16) - kcl.HEADER.second;
                 kcl.section3.count = kcl.HEADER.last - (kcl.HEADER.thirt + 16);
                 for (int i = 0; i < kcl.section1.count / 12; i++)
                 {
                     ListViewItem n = new ListViewItem(i.ToString());
                     float one = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 4096;
                     n.SubItems.Add(one.ToString());
                     float two = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 4096;
                     n.SubItems.Add(two.ToString());
                     float three = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 4096;
                     n.SubItems.Add(three.ToString());
                     listView1.Items.Add(n);
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p = new System.Windows.Forms.DataVisualization.Charting.DataPoint(one, three);
                     p.Color = Color.Transparent;
                     p.MarkerColor = Color.Red;
                     p.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                     chart1.Series[0].Points.Add(p);
                 }
                 for (int i = 0; i < kcl.section2.count / 6; i++)
                 {
                     ListViewItem n = new ListViewItem(i.ToString());
                     float one = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000") / 4096;
                     n.SubItems.Add(one.ToString());
                     float two = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000") / 4096;
                     n.SubItems.Add(two.ToString());
                     float three = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000") / 4096;
                     n.SubItems.Add(three.ToString());
                     listView2.Items.Add(n);
                 }
                 if (((double)(kcl.section2.count) / (double)(6)).ToString().EndsWith("33"))
                 {
                     br.ReadBytes(2);
                 }
                 for (int i = 0; i < kcl.section3.count / 16; i++)
                 {
                     ListViewItem n = new ListViewItem(i.ToString());
                     float one = parselittle2(System.BitConverter.ToString(br.ReadBytes(4)).Replace("-", "")) / 64000;
                     n.SubItems.Add(one.ToString());
                     float two = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000");
                     n.SubItems.Add(two.ToString());
                     float three = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000");
                     n.SubItems.Add(three.ToString());
                     float four = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000");
                     n.SubItems.Add(four.ToString());
                     float vife = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000");
                     n.SubItems.Add(vife.ToString());
                     float six = parselittle2(System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "") + "0000");
                     n.SubItems.Add(six.ToString());
                     string ground = System.BitConverter.ToString(br.ReadBytes(2)).Replace("-", "");
                     string second = "";
                     string first = ground.Remove(2, 2);
                     if (ground.Remove(0, 2).Remove(1, 1) == "0" || ground.Remove(0, 2).Remove(1, 1) == "2" || ground.Remove(0, 2).Remove(1, 1) == "4" || ground.Remove(0, 2).Remove(1, 1) == "6" ||
                         ground.Remove(0, 2).Remove(1, 1) == "8" || ground.Remove(0, 2).Remove(1, 1) == "A" || ground.Remove(0, 2).Remove(1, 1) == "C" || ground.Remove(0, 2).Remove(1, 1) == "E")
                     {
                         second += 0;
                         second += ground.Remove(0, 3);
                     }
                     else
                     {
                         second += 1;
                         second += ground.Remove(0, 3);
                     }
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p1 = new System.Windows.Forms.DataVisualization.Charting.DataPoint();
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p2 = new System.Windows.Forms.DataVisualization.Charting.DataPoint();
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p3 = new System.Windows.Forms.DataVisualization.Charting.DataPoint();
                     switch (second)
                     {
                         case "0D":
                         case "06":
                         case "01":
                         case "00":
                             n.SubItems.Add("Road");
                             p1.Color = Color.Gray;
                             p2.Color = Color.Gray;
                             p3.Color = Color.Gray;
                             break;
                         case "02":
                         case "03":
                         case "05":
                             if (first == "40")
                             {
                                 n.SubItems.Add("Grass");
                                 p1.Color = Color.Green;
                                 p2.Color = Color.Green;
                                 p3.Color = Color.Green;
                             }
                             else
                             {
                                 n.SubItems.Add("Sand");
                                 p1.Color = Color.Yellow;
                                 p2.Color = Color.Yellow;
                                 p3.Color = Color.Yellow;
                             }
                             break;
                         case "04":
                         case "0B":
                         case "0F":
                         case "16":
                             n.SubItems.Add("Fall");
                             p1.Color = Color.Black;
                             p2.Color = Color.Black;
                             p3.Color = Color.Black;
                             break;
                         case "07":
                         case "12":
                             n.SubItems.Add("Speed Boost");
                             p1.Color = Color.Red;
                             p2.Color = Color.Red;
                             p3.Color = Color.Red;
                             break;
                         case "08":
                         case "09":
                         case "10":
                         case "15":
                             n.SubItems.Add("Wall");
                             p1.Color = Color.Orange;
                             p2.Color = Color.Orange;
                             p3.Color = Color.Orange;
                             break;
                         case "0A":
                             n.SubItems.Add("Out of bounds");
                             p1.Color = Color.Black;
                             p2.Color = Color.Black;
                             p3.Color = Color.Black;
                             break;
                         default:
                             n.SubItems.Add(ground);
                             p1.Color = Color.Purple;
                             p2.Color = Color.Purple;
                             p3.Color = Color.Purple;
                             break;
                     }
                     n.SubItems[n.SubItems.Count - 1].Text += " (" + ground + ")";
                     listView3.Items.Add(n);

                     Chadsoft.CTools.Models.Matrix3x1 Position = new Chadsoft.CTools.Models.Matrix3x1((float)Convert.ToDouble(listView1.Items[(int)two].SubItems[1].Text), (float)Convert.ToDouble(listView1.Items[(int)two].SubItems[2].Text), (float)Convert.ToDouble(listView1.Items[(int)two].SubItems[3].Text));
                     Chadsoft.CTools.Models.Matrix3x1 Direction = new Chadsoft.CTools.Models.Matrix3x1((float)Convert.ToDouble(listView2.Items[(int)three].SubItems[1].Text), (float)Convert.ToDouble(listView2.Items[(int)three].SubItems[2].Text), (float)Convert.ToDouble(listView2.Items[(int)three].SubItems[3].Text));
                     Chadsoft.CTools.Models.Matrix3x1 NormalA = new Chadsoft.CTools.Models.Matrix3x1((float)Convert.ToDouble(listView2.Items[(int)four].SubItems[1].Text), (float)Convert.ToDouble(listView2.Items[(int)four].SubItems[2].Text), (float)Convert.ToDouble(listView2.Items[(int)four].SubItems[3].Text));
                     Chadsoft.CTools.Models.Matrix3x1 NormalB = new Chadsoft.CTools.Models.Matrix3x1((float)Convert.ToDouble(listView2.Items[(int)vife].SubItems[1].Text), (float)Convert.ToDouble(listView2.Items[(int)vife].SubItems[2].Text), (float)Convert.ToDouble(listView2.Items[(int)vife].SubItems[3].Text));
                     Chadsoft.CTools.Models.Matrix3x1 NormalC = new Chadsoft.CTools.Models.Matrix3x1((float)Convert.ToDouble(listView2.Items[(int)six].SubItems[1].Text), (float)Convert.ToDouble(listView2.Items[(int)six].SubItems[2].Text), (float)Convert.ToDouble(listView2.Items[(int)six].SubItems[3].Text));
                     //System.Windows.Forms.DataVisualization.Charting.Series s = new Series();
                     // s.ChartType = SeriesChartType.Range;
                    /*  float X1 = Position.X + Direction.Cross(NormalA).X * (one / NormalA.Dot(NormalC));
                      float Z1 = Position.Z + Direction.Cross(NormalA).Z * (one / NormalA.Dot(NormalC));
                     float X2 = Position.X + NormalB.Cross(Direction).X * (one / NormalB.Dot(NormalC));
                     float Z2 = Position.Z + NormalB.Cross(Direction).Z * (one / NormalB.Dot(NormalC));
                     try
                     {
                         Chadsoft.CTools.Models.Matrix3x1 Vertex1 = new Chadsoft.CTools.Models.Matrix3x1();
                         Chadsoft.CTools.Models.Matrix3x1 Vertex2 = new Chadsoft.CTools.Models.Matrix3x1();
                         Chadsoft.CTools.Models.Matrix3x1 Vertex3 = new Chadsoft.CTools.Models.Matrix3x1();

                         Vertex1 = Position;
                         Vertex2 = Position + Direction.Cross(NormalA) * (one / NormalA.Dot(NormalC)) / 4096;
                         Vertex3 = Position + NormalB.Cross(Direction) * (one / NormalB.Dot(NormalC));

                         p1.XValue = Vertex1.X;
                         p1.YValues[0] = Vertex1.Z;

                         p2.XValue = Vertex2.X;
                         p2.YValues[0] = Vertex2.Z;

                         p3.XValue = Vertex3.X;
                         p3.YValues[0] = Vertex3.Z;

                         if (float.IsNaN(Vertex1.X) || float.IsInfinity(Vertex1.X) || float.IsNaN(Vertex1.Z) || float.IsInfinity(Vertex1.Z) || float.IsNaN(Vertex2.X) || float.IsInfinity(Vertex2.X) || float.IsNaN(Vertex2.Z) || float.IsInfinity(Vertex2.Z) || float.IsNaN(Vertex3.X) || float.IsInfinity(Vertex3.X) || float.IsNaN(Vertex3.Z) || float.IsInfinity(Vertex3.Z))
                         {
                             throw new Exception("");
                         }

                        
                         System.Windows.Forms.DataVisualization.Charting.DataPoint empty = new System.Windows.Forms.DataVisualization.Charting.DataPoint();
                         empty.IsEmpty = true;
                        // chart1.Series[2].Points.Add(p1);
                       //  chart1.Series[2].Points.Add(p2);
                       //  chart1.Series[2].Points.Add(p3);
                        // chart1.Series[2].Points.Add(empty);
                     }
                     catch { }
                     //s.Points.AddXY(Position.X, Position.Z);
                     //s.Points.AddXY(X1, Z1);
                     //s.Points.AddXY(X2, Z2);
                     // s.Color = Color.Green;
                     //chart1.Series.Add(s);
                 }
                 OctreeNode.maxkids = 0;
                 int shift = (int)kcl.HEADER.Coordinate_shift;
                 Vector3 octreestart = new Vector3(kcl.HEADER.Spatial_grid_X, kcl.HEADER.Spatial_grid_Y, kcl.HEADER.Spatial_grid_Z);
                 float _cubesize = (float)(1 << shift); // 1024f;
                 Vector3 cubesize = new Vector3(_cubesize, _cubesize, _cubesize);
                 Vector3 octreesize = new Vector3((~(int)kcl.HEADER.X_Mask >> shift) + 1, (~(int)kcl.HEADER.Y_Mask >> shift) + 1, (~(int)kcl.HEADER.Z_Mask >> shift) + 1);
                 OctreeNode.m_List = new List<OctreeNode>();
                 uint loloffset = (uint)kcl.HEADER.last;
                 EndianBinaryReader er = new EndianBinaryReader(br.BaseStream, Endianness.LittleEndian);
                 List<OctreeNode> oc = new List<OctreeNode>();
                 for (int z = 0; z < octreesize.Z; z++)
                     for (int y = 0; y < octreesize.Y; y++)
                         for (int x = 0; x < octreesize.X; x++)
                         {
                             TreeNode tn = new TreeNode("Node");
                             oc.Add(new OctreeNode(er, (uint)kcl.HEADER.last, loloffset, octreestart + new Vector3(cubesize.X * x, cubesize.Y * y, cubesize.Z * z), cubesize, tn));
                             treeView1.Nodes.Add(oc[oc.Count - 1].node_);
                             loloffset += 4;
                         }
                 for (int i = 0; i < v3.Count; i++)
                 {
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                     p.Color = Color.Transparent;
                     p.MarkerColor = Color.Blue;
                     p.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                     chart1.Series[1].Points.Add(p);
                     System.Windows.Forms.DataVisualization.Charting.DataPoint s = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + v3_[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                     s.Color = Color.Transparent;
                     s.MarkerColor = Color.Blue;
                     s.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                     chart1.Series[1].Points.Add(s);
                     System.Windows.Forms.DataVisualization.Charting.DataPoint q = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + v3_[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                     q.Color = Color.Transparent;
                     q.MarkerColor = Color.Blue;
                     q.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                     chart1.Series[1].Points.Add(q);
                 }
                 br.Close();
             }
             else
             {
                 for (int i = 0; i < vx.Count; i++)
                 {
                     System.Windows.Forms.DataVisualization.Charting.DataPoint p = new System.Windows.Forms.DataVisualization.Charting.DataPoint(vx[i], vz[i]);
                     p.Color = Color.Transparent;
                     p.MarkerColor = Color.Red;
                     p.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                     chart1.Series[0].Points.Add(p);
                 }

             }*/
            Read();
        }
        /*class OctreeNode
        {
            public List<int> m_PlaneData;
            public OctreeNode[] m_Children;
            public int m_Depth;
            public uint m_BaseOffset, m_NodeOffset;

            public void Divide(List<PlanE> planes, Vector3 start, Vector3 size, bool dropextra, KCL_file k)
            {
                m_Children = new OctreeNode[8];
                size = Vector3.Divide(size, 2f);
                m_Children[0] = new OctreeNode(this, planes, start, size, m_Depth + 1, dropextra, k);
                m_Children[1] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(size.X, 0f, 0f)), size, m_Depth + 1, dropextra, k);
                m_Children[2] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(0f, size.Y, 0f)), size, m_Depth + 1, dropextra, k);
                m_Children[3] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(size.X, size.Y, 0f)), size, m_Depth + 1, dropextra, k);
                m_Children[4] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(0f, 0f, size.Z)), size, m_Depth + 1, dropextra, k);
                m_Children[5] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(size.X, 0f, size.Z)), size, m_Depth + 1, dropextra, k);
                m_Children[6] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(0f, size.Y, size.Z)), size, m_Depth + 1, dropextra, k);
                m_Children[7] = new OctreeNode(this, planes, Vector3.Add(start, new Vector3(size.X, size.Y, size.Z)), size, m_Depth + 1, dropextra, k);
                m_PlaneData = null;
            }
            static int nnodes = 0;
            static int maxdepth = 0;
            public static List<OctreeNode> lollist;
            public Vector3 _start, _size;
            public OctreeNode(OctreeNode parent, List<PlanE> planes, Vector3 start, Vector3 size, int depth, bool dropextra, KCL_file k)
            {
                nnodes++;
                m_Depth = depth;
                if (depth > maxdepth) maxdepth = depth;
                _start = start; _size = size;

                if (lollist == null) lollist = new List<OctreeNode>();
                lollist.Add(this);

                if (depth == 0)
                {
                    Divide(planes, start, size, dropextra, k);
                    /*m_Children = new OctreeNode[64];
                    size = Vector3.Divide(size, 4f);
                    int ic = 0;
                    for (int iz = 0; iz < 4; iz++)
                    {
                        for (int iy = 0; iy < 4; iy++)
                        {
                            for (int ix = 0; ix < 4; ix++)
                            {
                                Vector3 _start = Vector3.Add(start, new Vector3(size.X * ix, size.Y * iy, size.Z * iz));
                                m_Children[ic++] = new OctreeNode(this, planes, _start, size, 1);
                            }
                        }
                    }/
                    return;
                }

                m_Children = null;
                m_PlaneData = new List<int>();
                if (parent.m_PlaneData != null)
                {
                    foreach (int i in parent.m_PlaneData)
                    {
                        if (InCube(start, size, planes[i], k))
                            m_PlaneData.Add(i);
                    }
                }
                else
                {
                    for (int i = 0; i < planes.Count; i++)
                    {
                        if (InCube(start, size, planes[i], k))
                            m_PlaneData.Add(i);
                    }
                }

                // idk about the exact limit
                // goes up to 22 in the original models
                const int limit = 32;
                if (m_PlaneData.Count > limit)
                {
                    if (size.X > 0.25f)
                        Divide(planes, start, size, dropextra, k);
                    else if (dropextra)
                        m_PlaneData.RemoveRange(limit, m_PlaneData.Count - limit);
                }
            }

            public void WriteNode(EndianBinaryWriter file, ref uint pos)
            {
                m_NodeOffset = pos;
                pos += 4;
            }

            public void WriteChildren(EndianBinaryWriter file, uint basepos, ref uint pos)
            {
                m_BaseOffset = basepos;

                if (m_Children != null)
                {
                    if (m_Depth > 0)
                    {
                        file.BaseStream.Position = m_NodeOffset;
                        file.Write((Int32)(pos - m_BaseOffset));//.Write32(m_NodeOffset, pos - m_BaseOffset);
                    }
                    else
                        m_NodeOffset = basepos;

                    foreach (OctreeNode child in m_Children)
                        child.WriteNode(file, ref pos);

                    foreach (OctreeNode child in m_Children)
                        child.WriteChildren(file, m_Children[0].m_NodeOffset, ref pos);
                }
            }

            public void WritePlaneData(EndianBinaryWriter file, ref uint pos)
            {
                if (m_PlaneData != null)
                {
                    if (m_Depth > 0)
                    {
                        file.BaseStream.Position = m_NodeOffset;
                        file.Write((Int32)(0x80000000 | (pos - m_BaseOffset - 2)));//.Write32(m_NodeOffset, 0x80000000 | (pos - m_BaseOffset - 2));
                    }

                    foreach (int plane in m_PlaneData)
                    {
                        file.BaseStream.Position = pos;
                        file.Write((Int16)((ushort)(plane + 1)));//Write16(pos, (ushort)(plane + 1));
                        pos += 2;
                    }
                    file.BaseStream.Position = pos;
                    file.Write((Int16)0);//.Write16(pos, 0);
                    pos += 2;
                }

                if (m_Children != null)
                {
                    foreach (OctreeNode child in m_Children)
                        child.WritePlaneData(file, ref pos);
                    return;
                }
            }
        }*/
        public static bool InCube(Vector3 start, Vector3 cubesize, PlanE p, KCL_file k)
        {
            //if (m_Fake) return false;
            Vector3 Position = new Vector3(k.Vertex.Items[p.VertexIndex].X, k.Vertex.Items[p.VertexIndex].Y, k.Vertex.Items[p.VertexIndex].Z);
            Vector3 Direction = new Vector3(k.Normals.Items[p.NormalIndex].X, k.Normals.Items[p.NormalIndex].Y, k.Normals.Items[p.NormalIndex].Z);
            Vector3 NormalA = new Vector3(k.Normals.Items[p.NormalAIndex].X, k.Normals.Items[p.NormalAIndex].Y, k.Normals.Items[p.NormalAIndex].Z);
            Vector3 NormalB = new Vector3(k.Normals.Items[p.NormalBIndex].X, k.Normals.Items[p.NormalBIndex].Y, k.Normals.Items[p.NormalBIndex].Z);
            Vector3 NormalC = new Vector3(k.Normals.Items[p.NormalCIndex].X, k.Normals.Items[p.NormalCIndex].Y, k.Normals.Items[p.NormalCIndex].Z);
            Vector3 lol1 = Vector3.Cross(NormalA, Direction);
            float lol1len = p.Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol1, NormalC))));
            Vector3 tmp = Vector3.Add(Position, Vector3.Multiply(lol1, lol1len));

            Vector3 lol2 = Vector3.Cross(Direction, NormalB);
            float lol2len = p.Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol2, NormalC))));
            Vector3 tmp2 = Vector3.Add(Position, Vector3.Multiply(lol2, lol2len));

            Vector3 m_Point = Position;
            Vector3 m_PointB = tmp;
            Vector3 m_PointC = tmp2;

            //float epsilon = cubesize.X / 16f + 0.1f;
            float epsilon = Math.Max(cubesize.X / 16f, 0.1f);
            Vector3 cubecenter = Vector3.Add(start, Vector3.Divide(cubesize, 2f));

            Vector3 a2center = Vector3.Subtract(cubecenter, m_Point);
            Vector3 ab = Vector3.Subtract(m_PointB, m_Point);
            Vector3 ac = Vector3.Subtract(m_PointC, m_Point);
            Vector3 bc = Vector3.Subtract(m_PointC, m_PointB);
            Vector3 ca = Vector3.Subtract(m_Point, m_PointC);
            Vector3 normal = Vector3.Cross(ac, ab);

            // calculate the distance from the cube center to the plane
            float dist2plane = Vector3.Dot(a2center, normal) / normal.Length;
            Vector3 center2plane = Vector3.Multiply(normal, -dist2plane / normal.Length);
            Vector3 centeronplane = Vector3.Add(cubecenter, center2plane);

            // calculate the maximal distance to stay within the cube
            // if the plane is further, we can return early
            float dmax = Math.Max(Math.Abs(center2plane.X), Math.Max(Math.Abs(center2plane.Y), Math.Abs(center2plane.Z)));
            float maxdist = Vector3.Multiply(center2plane, cubesize.X / (2f * dmax)).Length; // consider the cube cubic, for speed
            if (center2plane.Length > maxdist + epsilon) return false;

            // if the projection of the cube center onto the plane is within the triangle,
            // consider the triangle to be in
            float dot1 = Vector3.Dot(Vector3.Cross(ab, Vector3.Subtract(centeronplane, m_Point)), normal);
            float dot2 = Vector3.Dot(Vector3.Cross(ca, Vector3.Subtract(centeronplane, m_PointC)), normal);
            float dot3 = Vector3.Dot(Vector3.Cross(bc, Vector3.Subtract(centeronplane, m_PointB)), normal);
            if (dot1 < 0f && dot2 < 0f && dot3 < 0f)
                return true;

            // otherwise, well...
            // calculate the distances from the cube center to each of the triangle's sides
            // if the smallest distance is within the cube, consider it good
            float r1 = Vector3.Dot(Vector3.Subtract(cubecenter, m_Point), ab) / ab.LengthSquared;
            float r2 = Vector3.Dot(Vector3.Subtract(cubecenter, m_PointC), ca) / ca.LengthSquared;
            float r3 = Vector3.Dot(Vector3.Subtract(cubecenter, m_PointB), bc) / bc.LengthSquared;
            r1 = Math.Max(0f, Math.Min(1f, r1));
            r2 = Math.Max(0f, Math.Min(1f, r2));
            r3 = Math.Max(0f, Math.Min(1f, r3));
            Vector3 p1 = Vector3.Add(m_Point, Vector3.Multiply(ab, r1));
            Vector3 p2 = Vector3.Add(m_PointC, Vector3.Multiply(ca, r2));
            Vector3 p3 = Vector3.Add(m_PointB, Vector3.Multiply(bc, r3));
            Vector3 d1 = Vector3.Subtract(p1, cubecenter);
            Vector3 d2 = Vector3.Subtract(p2, cubecenter);
            Vector3 d3 = Vector3.Subtract(p3, cubecenter);

            Vector3 d;
            if (d1.Length < Math.Min(d2.Length, d3.Length))
                d = d1;
            else if (d2.Length < d3.Length)
                d = d2;
            else
                d = d3;

            dmax = Math.Max(Math.Abs(d.X), Math.Max(Math.Abs(d.Y), Math.Abs(d.Z)));
            maxdist = Vector3.Multiply(d, cubesize.X / (2f * dmax)).Length;
            return d.Length <= maxdist + epsilon;
        }
        KCL_file k;
        void Read()
        {
            EndianBinaryReader er = new EndianBinaryReader(path_, Endianness.LittleEndian);
            k = new KCL_file();
            k.Header.Section1 = er.ReadInt32();
            k.Header.Section2 = er.ReadInt32();
            k.Header.Section3 = er.ReadInt32();
            k.Header.Section4 = er.ReadInt32();
            k.Header.Unknown1 = er.ReadBytes(4);
            k.Header.SpatialGridX = (float)er.ReadInt32() / 4096f;
            k.Header.SpatialGridY = (float)er.ReadInt32() / 4096f;
            k.Header.SpatialGridZ = (float)er.ReadInt32() / 4096f;
            k.Header.Xmask = er.ReadInt32();
            k.Header.Ymask = er.ReadInt32();
            k.Header.Zmask = er.ReadInt32();
            k.Header.Coordinate_shift = er.ReadInt32();
            k.Header.YShift = er.ReadInt32();
            k.Header.ZShift = er.ReadInt32();
            k.Header.Unknown2 = er.ReadBytes(4);
            er.BaseStream.Position = k.Header.Section1;
            k.Vertex.Items = new List<VerteX>();
            for (int i = 0; i < (k.Header.Section2 - k.Header.Section1) / 0xC; i++)
            {
                k.Vertex.Items.Add(new VerteX());
                k.Vertex.Items[i].X = (float)er.ReadInt32() / 4096f;
                k.Vertex.Items[i].Y = (float)er.ReadInt32() / 4096f;
                k.Vertex.Items[i].Z = (float)er.ReadInt32() / 4096f;
                ListViewItem n = new ListViewItem((i + 1).ToString());
                n.SubItems.Add(k.Vertex.Items[i].X.ToString());
                n.SubItems.Add(k.Vertex.Items[i].Y.ToString());
                n.SubItems.Add(k.Vertex.Items[i].Z.ToString());
                listView1.Items.Add(n);
                kclEditorControl1.Vertex.Add(k.Vertex.Items[i].X, k.Vertex.Items[i].Y, k.Vertex.Items[i].Z, Color.Red);
            }
            er.BaseStream.Position = k.Header.Section2;
            k.Normals.Items = new List<NormaL>();
            for (int i = 0; i < ((k.Header.Section3 + 0x10) - k.Header.Section2) / 0x6; i++)
            {
                k.Normals.Items.Add(new NormaL());
                k.Normals.Items[i].X = (float)er.ReadInt16() / 4096f;
                k.Normals.Items[i].Y = (float)er.ReadInt16() / 4096f;
                k.Normals.Items[i].Z = (float)er.ReadInt16() / 4096f;
                ListViewItem n = new ListViewItem((i + 1).ToString());
                n.SubItems.Add(k.Normals.Items[i].X.ToString());
                n.SubItems.Add(k.Normals.Items[i].Y.ToString());
                n.SubItems.Add(k.Normals.Items[i].Z.ToString());
                listView2.Items.Add(n);
            }
            er.BaseStream.Position = k.Header.Section3 + 0x10;
            k.Planes.Items = new List<PlanE>();
            polys[0] = new List<Vector3>();
            polys[1] = new List<Vector3>();
            polys[2] = new List<Vector3>();
            for (int i = 0; i < (k.Header.Section4 - (k.Header.Section3 + 0x10)) / 0x10; i++)
            {
                k.Planes.Items.Add(new PlanE());
                k.Planes.Items[i].Length = /*er.ReadSingle();*/(float)er.ReadInt32() / 4096f; /* (8192 * 2);*/ // /*(65536000f / 4000f)* //64000f; //65536000f;
                k.Planes.Items[i].VertexIndex = er.ReadInt16();
                k.Planes.Items[i].NormalIndex = er.ReadInt16();
                k.Planes.Items[i].NormalAIndex = er.ReadInt16();
                k.Planes.Items[i].NormalBIndex = er.ReadInt16();
                k.Planes.Items[i].NormalCIndex = er.ReadInt16();
                k.Planes.Items[i].Type = er.ReadBytes(2);
                ListViewItem n = new ListViewItem((i + 1).ToString());
                n.SubItems.Add(k.Planes.Items[i].Length.ToString());
                n.SubItems.Add(k.Planes.Items[i].VertexIndex.ToString());
                n.SubItems.Add(k.Planes.Items[i].NormalIndex.ToString());
                n.SubItems.Add(k.Planes.Items[i].NormalAIndex.ToString());
                n.SubItems.Add(k.Planes.Items[i].NormalBIndex.ToString());
                n.SubItems.Add(k.Planes.Items[i].NormalCIndex.ToString());
                string second2 = "";
                byte first = k.Planes.Items[i].Type[0];
                if (BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "0" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "2" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "4" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "6" ||
                    BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "8" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "A" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "C" || BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 2).Remove(1, 1) == "E")
                {
                    second2 += 0;
                    second2 += BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 3);
                }
                else
                {
                    second2 += 1;
                    second2 += BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "").Remove(0, 3);
                }
                byte second = byte.Parse(second2, System.Globalization.NumberStyles.HexNumber);
                Color c;
                n.SubItems.Add(getType(out c, first, second));
                n.SubItems[n.SubItems.Count - 1].Text += " (" + BitConverter.ToString(k.Planes.Items[i].Type).Replace("-", "") + ")";
                listView3.Items.Add(n);
                Vector3 Position = new Vector3(k.Vertex.Items[k.Planes.Items[i].VertexIndex].X, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Y, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Z);
                Vector3 Direction = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalIndex].X, k.Normals.Items[k.Planes.Items[i].NormalIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalIndex].Z);
                Vector3 NormalA = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalAIndex].X, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Z);
                Vector3 NormalB = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalBIndex].X, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Z);
                Vector3 NormalC = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalCIndex].X, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Z);
                Vector3 lol1 = Vector3.Cross(NormalA, Direction);
                float lol1len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol1, NormalC))));
                Vector3 tmp = Vector3.Add(Position, Vector3.Multiply(lol1, lol1len));

                Vector3 lol2 = Vector3.Cross(Direction, NormalB);
                float lol2len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol2, NormalC))));
                Vector3 tmp2 = Vector3.Add(Position, Vector3.Multiply(lol2, lol2len));
                kclEditorControl1.Planes.Add(Position.X, Position.Y, Position.Z, tmp.X, tmp.Y, tmp.Z, tmp2.X, tmp2.Y, tmp2.Z, c);
                polys[0].Add(Position);
                polys[1].Add(tmp);
                polys[2].Add(tmp2);
                colors.Add(c);
            }
            long pos = er.BaseStream.Position;
            int nodes = ((~k.Header.Xmask >> k.Header.Coordinate_shift) + 1) *
               ((~k.Header.Ymask >> k.Header.Coordinate_shift) + 1) *
               ((~k.Header.Zmask >> k.Header.Coordinate_shift) + 1);
            k.Octree = new KclOctreeNode(er, nodes);
            treeView1.Nodes.AddRange(k.Octree.GetNodes());
            Octree[0] = new List<Vector3>();
            Octree[1] = new List<Vector3>();
            Octree[2] = new List<Vector3>();
            er.BaseStream.Position = pos;
            byte[] oct = er.ReadBytes((int)er.BaseStream.Length - (int)pos);
            k.octree = oct;
            /*OctreeNode.maxkids = 0;
            int shift = (int)k.Header.Coordinate_shift;
            Vector3 octreestart = new Vector3(k.Header.SpatialGridX, k.Header.SpatialGridY, k.Header.SpatialGridZ);
            float _cubesize = (float)(1 << shift); // 1024f;
            Vector3 cubesize = new Vector3(_cubesize, _cubesize, _cubesize);
            Vector3 octreesize = new Vector3((~(int)k.Header.Xmask >> shift) + 1, (~(int)k.Header.Ymask >> shift) + 1, (~(int)k.Header.Zmask>> shift) + 1);
            OctreeNode.m_List = new List<OctreeNode>();
            uint loloffset = (uint)k.Header.Section4;
            List<OctreeNode> oc = new List<OctreeNode>();
            for (int z = 0; z < octreesize.Z; z++)
                for (int y = 0; y < octreesize.Y; y++)
                    for (int x = 0; x < octreesize.X; x++)
                    {
                        TreeNode tn = new TreeNode("Node");
                        oc.Add(new OctreeNode(er, (uint)k.Header.Section4, loloffset, octreestart + new Vector3(cubesize.X * x, cubesize.Y * y, cubesize.Z * z), cubesize, tn));
                        treeView1.Nodes.Add(oc[oc.Count - 1].node_);
                        loloffset += 4;
                    }
            for (int i = 0; i < v3.Count; i++)
            {
                /*System.Windows.Forms.DataVisualization.Charting.DataPoint p = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                p.Color = Color.Transparent;
                p.MarkerColor = Color.Blue;
                p.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                chart1.Series[1].Points.Add(p);
                System.Windows.Forms.DataVisualization.Charting.DataPoint s = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + v3_[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                s.Color = Color.Transparent;
                s.MarkerColor = Color.Blue;
                s.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                chart1.Series[1].Points.Add(s);
                System.Windows.Forms.DataVisualization.Charting.DataPoint q = new System.Windows.Forms.DataVisualization.Charting.DataPoint(v3[i].X + ((kcl.HEADER.Spatial_grid_X * kcl.HEADER.Coordinate_shift) * 1.5f), v3[i].Z + v3_[i].Z + ((kcl.HEADER.Spatial_grid_Z * kcl.HEADER.Coordinate_shift) * 1.5f));
                q.Color = Color.Transparent;
                q.MarkerColor = Color.Blue;
                q.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
                chart1.Series[1].Points.Add(q);
            }*/
            er.Close();
            RenderFunc1();
        }
        public static string getType(byte first, byte second)
        {
            Color c;
            return getType(out c, first, second);
        }
        public static string getType(out Color co, byte first, byte second)
        {
            Color c;
            string s = "";
            switch (second)
            {
                case 0x06:
                    if (first == 0x20)
                    {
                        s = "Mud";
                        c = System.Drawing.ColorTranslator.FromHtml("#6F4E37");
                    }
                    else
                    {
                        s = "Road";
                        c = Color.Gray;
                    }
                    break;
                case 0x0D:
                case 0x01:
                    s = "Road";
                    c = Color.Gray;
                    break;
                case 0x00:
                    if (first == 0x80)
                    {
                        s = "Wood Road";
                        c = System.Drawing.ColorTranslator.FromHtml("#964B00");
                    }
                    else if (first == 0x02)
                    {
                        s = "Road with shadow";
                        c = System.Drawing.ColorTranslator.FromHtml("#404040");
                    }
                    else
                    {
                        s = "Road";
                        c = Color.Gray;
                    }
                    break;
                case 0x02:
                    {
                        s = "Sand";
                        c = Color.Yellow;
                        break;
                    }
                case 0x03:
                    {
                        if (first == 0xA0)
                        {
                            s = "Snow";
                            c = Color.Snow;
                        }
                        else
                        {
                            s = "Sand";
                            c = Color.Yellow;
                        }
                        break;
                    }
                case 0x05:
                    if (first == 0x40)
                    {
                        s = "Grass";
                        c = Color.Green;
                    }
                    else if (first == 0x80)
                    {
                        s = "Flowerbed";
                        c = Color.GreenYellow;
                    }
                    else
                    {
                        s = "Sand";
                        c = Color.Yellow;
                    }
                    break;
                case 0x0B:
                    if (first == 0x20)
                    {
                        s = "Fall (Water)";
                        c = Color.DarkBlue;
                    }
                    else
                    {
                        s = "Fall";
                        c = Color.Black;
                    }
                    break;
                case 0x04:
                case 0x0F:
                case 0x16:
                    s = "Fall";
                    c = Color.Black;
                    break;
                case 0x07:
                case 0x13:
                case 0x12:
                    s = "Speed Boost";
                    c = Color.Red;
                    break;
                case 0x08:
                case 0x09:
                case 0x10:
                    s = "Wall";
                    c = Color.Orange;
                    break;
                case 0x15:
                    if (first == 0x80)
                    {
                        s = "Bush";
                        c = Color.DarkGreen;
                    }
                    else
                    {
                        s = "Wall";
                        c = Color.Orange;
                    }
                    break;
                case 0x0A:
                    if (first == 0x60)
                    {
                        s = "Out of bounds (Snow)";
                        c = Color.Snow;
                    }
                    else
                    {
                        s = "Out of bounds";
                        c = Color.Black;
                    }
                    break;
                case 0x11:
                    s = "Water";
                    c = Color.SkyBlue;
                    break;
                default:
                    s = "?";
                    c = Color.Purple;
                    break;
            }
            co = c;
            return s;
        }
        public List<Vector3>[] polys = new List<Vector3>[3];
        public List<Color> colors = new List<Color>();
        public List<Vector3>[] Octree = new List<Vector3>[3];
        public struct KCL_file
        {
            public header Header;
            public struct header
            {
                public Int32 Section1;
                public Int32 Section2;
                public Int32 Section3;
                public Int32 Section4;
                public byte[] Unknown1;
                public float SpatialGridX;
                public float SpatialGridY;
                public float SpatialGridZ;
                public Int32 Xmask;
                public Int32 Ymask;
                public Int32 Zmask;
                public Int32 Coordinate_shift;
                public Int32 YShift;
                public Int32 ZShift;
                public byte[] Unknown2;
            }
            public vertex Vertex;
            public struct vertex
            {
                public List<VerteX> Items;
            }
            public normal Normals;
            public struct normal
            {
                public List<NormaL> Items;
            }
            public plane Planes;
            public struct plane
            {
                public List<PlanE> Items;
            }
            public KclOctreeNode Octree;
            public byte[] octree;
        }
        public class VerteX
        {
            public float X;
            public float Y;
            public float Z;
            public VerteX(Vector3 v)
            {
                X = v.X;
                Y = v.Y;
                Z = v.Z;
            }
            public VerteX()
            {
                X = 0;
                Y = 0;
                Z = 0;
            }
            public Vector3 ToVector3()
            {
                return new Vector3(X, Y, Z);
            }
        }
        public class NormaL
        {
            public float X;
            public float Y;
            public float Z;
            public NormaL(Vector3 v)
            {
                X = v.X;
                Y = v.Y;
                Z = v.Z;
            }
            public NormaL()
            {
                X = 0;
                Y = 0;
                Z = 0;
            }
            public Vector3 Cross(NormaL c)
            {
                Vector3 a = new Vector3(X, Y, Z);
                Vector3 b = new Vector3(c.X, c.Y, c.Z);
                return Vector3.Cross(a, b);
            }
            public Vector3 ToVector3()
            {
                return new Vector3(X, Y, Z);
            }
        }
        public class PlanE
        {
            public float Length;
            public short VertexIndex;
            public short NormalIndex;
            public short NormalAIndex;
            public short NormalBIndex;
            public short NormalCIndex;
            public byte[] Type;
        }
        public class OctreE
        {

        }
        int parselittle(string input)
        {
            int test = 0;
            test = int.Parse(input.ToCharArray()[6].ToString() + input.ToCharArray()[7].ToString() + input.ToCharArray()[4].ToString() + input.ToCharArray()[5].ToString() + input.ToCharArray()[2].ToString() + input.ToCharArray()[3].ToString() + input.ToCharArray()[0].ToString() + input.ToCharArray()[1].ToString(), System.Globalization.NumberStyles.HexNumber);
            return test;
        }
        public static List<Vector3> v3 = new List<Vector3>();
        public static List<Vector3> v3_ = new List<Vector3>();


        float parselittle2(string input)
        {
            float test2 = 0;
            test2 = int.Parse(input.ToCharArray()[6].ToString() + input.ToCharArray()[7].ToString() + input.ToCharArray()[4].ToString() + input.ToCharArray()[5].ToString() + input.ToCharArray()[2].ToString() + input.ToCharArray()[3].ToString() + input.ToCharArray()[0].ToString() + input.ToCharArray()[1].ToString(), System.Globalization.NumberStyles.HexNumber);
            return test2;
        }


        private void chart1_MouseUp(object sender, MouseEventArgs e)
        {

        }

        private void kcl_FormClosing(object sender, FormClosingEventArgs e)
        {
            v3.Clear();
            v3_.Clear();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            EndianBinaryWriter er = new EndianBinaryWriter(File.Create(path), Endianness.LittleEndian);
            er.Write((Int32)k.Header.Section1);
            er.Write((Int32)k.Header.Section2);
            er.Write((Int32)k.Header.Section3);
            er.Write((Int32)k.Header.Section4);
            er.Write(k.Header.Unknown1, 0, 4);
            er.Write((Int32)(k.Header.SpatialGridX * 4096));
            er.Write((Int32)(k.Header.SpatialGridY * 4096));
            er.Write((Int32)(k.Header.SpatialGridZ * 4096));
            er.Write((Int32)(k.Header.Xmask));
            er.Write((Int32)(k.Header.Ymask));
            er.Write((Int32)(k.Header.Zmask));
            er.Write((Int32)k.Header.Coordinate_shift);
            er.Write((Int32)k.Header.YShift);
            er.Write((Int32)k.Header.ZShift);
            er.Write(k.Header.Unknown2, 0, 4);
            for (int i = 0; i < k.Vertex.Items.Count; i++)
            {
                er.Write((Int32)(k.Vertex.Items[i].X * 4096));
                er.Write((Int32)(k.Vertex.Items[i].Y * 4096));
                er.Write((Int32)(k.Vertex.Items[i].Z * 4096));
            }
            int pos = (int)er.BaseStream.Position;
            er.BaseStream.Position = 4;
            er.Write((Int32)pos);
            er.BaseStream.Position = pos;
            for (int i = 0; i < k.Normals.Items.Count; i++)
            {
                er.Write((Int16)(k.Normals.Items[i].X * 4096));
                er.Write((Int16)(k.Normals.Items[i].Y * 4096));
                er.Write((Int16)(k.Normals.Items[i].Z * 4096));
            }
            while ((int)er.BaseStream.Length % 4 != 0) { er.Write((Byte)0); }
            pos = (int)er.BaseStream.Position;
            er.BaseStream.Position = 8;
            er.Write((Int32)(pos - 0x10));
            er.BaseStream.Position = pos;
            for (int i = 0; i < k.Planes.Items.Count; i++)
            {
                er.Write((Int32)(k.Planes.Items[i].Length * 4096));
                er.Write((Int16)(k.Planes.Items[i].VertexIndex));
                er.Write((Int16)(k.Planes.Items[i].NormalIndex));
                er.Write((Int16)(k.Planes.Items[i].NormalAIndex));
                er.Write((Int16)(k.Planes.Items[i].NormalBIndex));
                er.Write((Int16)(k.Planes.Items[i].NormalCIndex));
                er.Write(k.Planes.Items[i].Type, 0, 2);
            }
            pos = (int)er.BaseStream.Position;
            er.BaseStream.Position = 12;
            er.Write((Int32)pos);
            er.BaseStream.Position = pos;

            //k.Octree.Write(er);
            er.Write(k.octree, 0, k.octree.Length);
            // OctreeNode octree = new OctreeNode(null, k.Planes.Items, new Vector3(k.Header.SpatialGridX, k.Header.SpatialGridY, k.Header.SpatialGridZ), new Vector3(/*k.Header.Xmask, k.Header.Ymask,k.Header.Zmask*/15f,15f,15f), 0, k);
            //uint dataoffset = (uint)pos;
            //octree.WriteChildren(er, dataoffset, ref dataoffset);
            //octree.WritePlaneData(er, ref dataoffset);
            er.Close();
        }
        public static float X = 0.0f;
        public static float Y = 0.0f;
        public static float ang = 0.0f;
        public static float dist = 0.0f;//2.5
        public static float elev = 0.0f;
        private void RenderFunc1()
        {

            Gl.glViewport(0, 0, this.Width, this.Height);
            var vp = new[] { 0f, 0f, 0f, 0f };
            Gl.glGetFloatv(Gl.GL_VIEWPORT, vp);
            float aspect = (vp[2] - vp[0]) / (vp[3] - vp[1]);
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Glu.gluPerspective(90.0f, aspect, 0.02f, 50f);//0.02f, 32.0f);
            float gcd = GCD(Width, Height);

            Gl.glFrustum(-((float)Width / gcd), ((float)Width / gcd), -((float)Height / gcd), ((float)Height / gcd), 0, 0);  // apply the projection matrix
            //Gl.glEnable(Gl.GL_DITHER);
            //Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            //Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
            //Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, new float[] { 1f, 1f, 1f, 1f });
            //Gl.glEnable(Gl.GL_LIGHTING);
            //Gl.glEnable(Gl.GL_LIGHT0);

            Gl.glEnable(Gl.GL_ALPHA_TEST);

            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
            if (true)
            {
                Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
                Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(1.0f, 1.0f, 1.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(1.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 1.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 1.0f);
                Gl.glEnd();
                Gl.glRasterPos3f(1.0f, 0.0f, 0.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'X');
                Gl.glRasterPos3f(0.0f, 1.0f, 0.0f);
                // Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Y');
                Gl.glRasterPos3f(0.0f, 0.0f, 1.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Z');
            }
            Gl.glTranslatef(X, Y, -dist);
            Gl.glRotatef(elev, 1, 0, 0);
            Gl.glRotatef(ang, 0, 1, 0);

            Gl.glClearColor(51f / 255f, 51f / 255f, 51f / 255f, 1f);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glDisable(Gl.GL_CULL_FACE);
            Glu.GLUquadric q = Glu.gluNewQuadric();
            Glu.gluSphere(q, 0.0201f, 50, 50);
            /*Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glEnable(Gl.GL_LIGHT0);
            Gl.glEnable(Gl.GL_LIGHT1);
            Gl.glDisable(Gl.GL_LIGHT2);
            Gl.glDisable(Gl.GL_LIGHT3);*/
            try
            {
                for (int i = 0; i < polys[0].Count; i++)
                {
                    Gl.glBegin(Gl.GL_TRIANGLES);
                    Color cc = Color.FromArgb(i + 1);
                    Gl.glColor4f((float)cc.R / 255f, (float)cc.G / 255f, (float)cc.B / 255f, (float)cc.A / 255f);
                    Gl.glVertex3f(polys[0][i].X / 1024f, polys[0][i].Y / 1024f, polys[0][i].Z / 1024f);
                    Gl.glVertex3f(polys[1][i].X / 1024f, polys[1][i].Y / 1024f, polys[1][i].Z / 1024f);
                    Gl.glVertex3f(polys[2][i].X / 1024f, polys[2][i].Y / 1024f, polys[2][i].Z / 1024f);
                    Gl.glEnd();
                }
                Gl.glFlush();
                uint[] cols = new uint[] { 0 };
                Gl.glReadPixels(m_x, m_y, 1, 1, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, cols);
                col = cols[0];
                for (int i = 0; i < polys[0].Count; i++)
                {
                    Gl.glBegin(Gl.GL_TRIANGLES);
                    Gl.glColor3f((float)colors[i].R / 255f, (float)colors[i].G / 255f, (float)colors[i].B / 255f);
                    Gl.glVertex3f(polys[0][i].X / 1024f, polys[0][i].Y / 1024f, polys[0][i].Z / 1024f);
                    Gl.glVertex3f(polys[1][i].X / 1024f, polys[1][i].Y / 1024f, polys[1][i].Z / 1024f);
                    Gl.glVertex3f(polys[2][i].X / 1024f, polys[2][i].Y / 1024f, polys[2][i].Z / 1024f);
                    Gl.glEnd();
                }
                Vector3 octreesize = new Vector3((~k.Header.Xmask >> k.Header.Coordinate_shift) + 1, (~k.Header.Ymask >> k.Header.Coordinate_shift) + 1, (~k.Header.Zmask >> k.Header.Coordinate_shift) + 1);
                int nr = 0;
                for (int z = 0; z < octreesize.Z; z++)
                    for (int y = 0; y < octreesize.Y; y++)
                        for (int x = 0; x < octreesize.X; x++)
                        {
                            k.Octree.Nodes[nr].DrawNodes((float)(Math.Pow(2, k.Header.Coordinate_shift)), new Vector3(k.Header.SpatialGridX, k.Header.SpatialGridY, k.Header.SpatialGridZ) + new Vector3((float)(Math.Pow(2, k.Header.Coordinate_shift)) * x, (float)(Math.Pow(2, k.Header.Coordinate_shift)) * y,(float)(Math.Pow(2, k.Header.Coordinate_shift)) * z));
                            nr++;
                        }
                /*var mod = _nsbmd.models[0];
                if (mod == null)
                    return;
                renderer.Model = _nsbmd.models[0];
                renderer.RenderModel(file_2, ani, aniframeS, aniframeT, aniScaleS, aniScaleT, aniframeR, ca);*/
                // t2.Model = nsbm2.models[0];
                //t2.RenderModel(file_2, ani2, aniframeS2, aniframeT2, aniScaleS2, aniScaleT2, ca);
                //renderer.WriteOBJ(null, "C:\\test.obj");
            }
            catch (Exception ex)
            {
            }
            //Gl.glMatrixMode(Gl.GL_TEXTURE);
            //Gl.glRotatef(45, 1, 0, 0);
        }
        // <summary> 
        /// Greatest Common Denominator (GCD). Euclidean algorithm.  
        /// </summary> 
        /// <param name="a">Width.</param> 
        /// <param name="b">Height.</param> 
        /// <returns>GCD.</returns> 
        static int GCD(int a, int b)
        {
            return b == 0 ? a : GCD(b, a % b);
        }
        public bool wire = false;
        public int fix = 0;
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Right:
                    ang += 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Left:
                    ang -= 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Up:
                    elev += 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Down:
                    elev -= 1;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.Z:
                    X -= 0.05f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.X:
                    X += 0.05f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.A:
                    Y -= 0.05f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.S:
                    Y += 0.05f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.W:
                    if (wire == false)
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
                        simpleOpenGlControl1.Invalidate();
                        RenderFunc1(); ;
                        wire = true;
                    }
                    else
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
                        simpleOpenGlControl1.Invalidate();
                        RenderFunc1(); ;
                        wire = false;
                    }
                    return true;
                case Keys.Escape:
                    X = 0.0f;
                    Y = 0.0f;
                    ang = 0.0f;
                    dist = 0.0f;
                    elev = 0.0f;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                case Keys.T:
                    elev = 90;
                    ang = 0;
                    simpleOpenGlControl1.Invalidate();
                    RenderFunc1(); ;
                    return true;
                default:
                    return base.ProcessCmdKey(ref msg, keyData);
            }
        }

        private void simpleOpenGlControl1_Resize(object sender, EventArgs e)
        {
            simpleOpenGlControl1.Invalidate();
            RenderFunc1();
        }

        private void tabPage7_Click(object sender, EventArgs e)
        {
            RenderFunc1();
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            RenderFunc1();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            File.Create(@"C:\test.obj").Close();
            TextWriter tw = new StreamWriter(@"C:\test.obj");
            tw.WriteLine("# Created by MKDS Course Modifier");
            try
            {
                for (int i = 0; i < k.Planes.Items.Count; i++)
                {
                    Vector3 Position = new Vector3(k.Vertex.Items[k.Planes.Items[i].VertexIndex].X, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Y, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Z);
                    Vector3 Direction = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalIndex].X, k.Normals.Items[k.Planes.Items[i].NormalIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalIndex].Z);
                    Vector3 NormalA = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalAIndex].X, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Z);
                    Vector3 NormalB = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalBIndex].X, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Z);
                    Vector3 NormalC = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalCIndex].X, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Z);
                    Vector3 lol1 = Vector3.Cross(NormalA, Direction);
                    float lol1len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol1, NormalC))));
                    Vector3 tmp = Vector3.Add(Position, Vector3.Multiply(lol1, lol1len));

                    Vector3 lol2 = Vector3.Cross(Direction, NormalB);
                    float lol2len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol2, NormalC))));
                    Vector3 tmp2 = Vector3.Add(Position, Vector3.Multiply(lol2, lol2len));
                    //kclEditorControl1.Planes.Add(Position.X, Position.Y, Position.Z, tmp.X, tmp.Y, tmp.Z, tmp2.X, tmp2.Y, tmp2.Z, c);
                    //polys[0].Add(Position);
                    //polys[1].Add(tmp);
                    //polys[2].Add(tmp2);
                    tw.WriteLine("v {0} {1} {2}", (Position.X).ToString().Replace(",", "."), (Position.Y).ToString().Replace(",", "."), (Position.Z).ToString().Replace(",", "."));
                    tw.WriteLine("v {0} {1} {2}", (tmp.X).ToString().Replace(",", "."), (tmp.Y).ToString().Replace(",", "."), (tmp.Z).ToString().Replace(",", "."));
                    tw.WriteLine("v {0} {1} {2}", (tmp2.X).ToString().Replace(",", "."), (tmp2.Y).ToString().Replace(",", "."), (tmp2.Z).ToString().Replace(",", "."));
                }
                int nr = 1;
                for (int i = 0; i < k.Planes.Items.Count; i++)
                {
                    //if (vertex_normal[i] != -1)
                    //{
                    //    tw.WriteLine("f {0}//{3} {1}//{4} {2}//{5}", i + 1, i + 2, i + 3, vertex_normal[i], vertex_normal[i + 1], vertex_normal[i + 2]);
                    // tw.WriteLine("f {2}//{5} {1}//{4} {0}//{3}", i + 4, i + 2, i + 3, vertex_normal[i+3], vertex_normal[i + 1], vertex_normal[i]);
                    //}
                    //else
                    //{
                    tw.WriteLine("f {0} {1} {2}", nr, nr + 1, nr + 2);
                    //}
                    // if (nr == 3)
                    // {
                    //     nr = 0;
                    //     i += 3;
                    // }
                    // else
                    // {
                    //     nr++;
                    //}
                    nr += 3;
                }
                tw.Close();
            }
            catch
            {
                tw.Close();
            }
            /*HelixToolkit.MeshBuilder m = new HelixToolkit.MeshBuilder();
            for (int i = 0; i < k.Planes.Items.Count; i++)
            {
                Vector3 Position = new Vector3(k.Vertex.Items[k.Planes.Items[i].VertexIndex].X, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Y, k.Vertex.Items[k.Planes.Items[i].VertexIndex].Z);
                Vector3 Direction = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalIndex].X, k.Normals.Items[k.Planes.Items[i].NormalIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalIndex].Z);
                Vector3 NormalA = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalAIndex].X, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalAIndex].Z);
                Vector3 NormalB = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalBIndex].X, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalBIndex].Z);
                Vector3 NormalC = new Vector3(k.Normals.Items[k.Planes.Items[i].NormalCIndex].X, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Y, k.Normals.Items[k.Planes.Items[i].NormalCIndex].Z);
                Vector3 lol1 = Vector3.Cross(NormalA, Direction);
                float lol1len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol1, NormalC))));
                Vector3 tmp = Vector3.Add(Position, Vector3.Multiply(lol1, lol1len));

                Vector3 lol2 = Vector3.Cross(Direction, NormalB);
                float lol2len = k.Planes.Items[i].Length / (float)Math.Cos(Math.Acos(Math.Min(1f, Vector3.Dot(lol2, NormalC))));
                Vector3 tmp2 = Vector3.Add(Position, Vector3.Multiply(lol2, lol2len));
                //kclEditorControl1.Planes.Add(Position.X, Position.Y, Position.Z, tmp.X, tmp.Y, tmp.Z, tmp2.X, tmp2.Y, tmp2.Z, c);
                //polys[0].Add(Position);
                //polys[1].Add(tmp);
                //polys[2].Add(tmp2);
                m.AddTriangle(new System.Windows.Media.Media3D.Point3D(Position.X, Position.Y, Position.Z), new System.Windows.Media.Media3D.Point3D(tmp.X, tmp.Y, tmp.Z), new System.Windows.Media.Media3D.Point3D(tmp2.X, tmp2.Y, tmp2.Z));
                //tw.WriteLine("v {0} {1} {2}", (Position.X).ToString().Replace(",", "."), (Position.Y).ToString().Replace(",", "."), (Position.Z).ToString().Replace(",", "."));
                //tw.WriteLine("v {0} {1} {2}", (tmp.X).ToString().Replace(",", "."), (tmp.Y).ToString().Replace(",", "."), (tmp.Z).ToString().Replace(",", "."));
                //tw.WriteLine("v {0} {1} {2}", (tmp2.X).ToString().Replace(",", "."), (tmp2.Y).ToString().Replace(",", "."), (tmp2.Z).ToString().Replace(",", "."));
            }
            HelixToolkit.ObjExporter o = new HelixToolkit.ObjExporter(@"C:\test.obj", "Created with MKDS Course Modifier");
            o.ExportMesh(m.ToMesh(), System.Windows.Media.Media3D.Transform3D.Identity);*/
        }
        PlaneProperty p = null;
        private void listView3_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (p != null)
            {
                colors[p.ID] = p.co;
                kclEditorControl1.Planes[p.ID].MarkerColor = p.co;
            }
            if (listView3.SelectedIndices.Count != 0)
            {
                p = new PlaneProperty();
                p.SetCollisionType(k.Planes.Items[listView3.SelectedIndices[0]].Type);
                p.SetPositions(polys[0][listView3.SelectedIndices[0]], polys[1][listView3.SelectedIndices[0]], polys[2][listView3.SelectedIndices[0]]);
                p.Plane = k.Planes.Items[listView3.SelectedIndices[0]];
                p.ListViewNode = listView3.SelectedItems[0];
                p.co = colors[listView3.SelectedIndices[0]];
                p.ID = listView3.SelectedIndices[0];
                propertyGrid1.SelectedObject = p;
            }
            else
            {

                propertyGrid1.SelectedObject = null;
            }
        }
        public class PlaneProperty
        {
            public int ID;
            public PlanE Plane;
            public Color co;
            public ListViewItem ListViewNode;
            public void SetCollisionType(byte[] Type)
            {
                ct = Type;
            }
            private byte[] ct;
            [Category("Plane Properties"), DefaultValue(0), DisplayName("Collision Type"), TypeConverter(typeof(UInt16HexTypeConverter)), Description("This is the type of the collision. For example: Grass, Road, Wall.")]
            public UInt16 CollisionType
            {
                get { return UInt16.Parse(BitConverter.ToString(ct).Replace("-", ""), System.Globalization.NumberStyles.HexNumber); }
                set
                {
                    ct = stringtobyte(string.Format("{0:x4}", value));
                    Plane.Type = ct;
                    byte first = ct[0];
                    string second2 = "";
                    if (BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "0" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "2" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "4" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "6" ||
                        BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "8" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "A" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "C" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "E")
                    {
                        second2 += 0;
                        second2 += BitConverter.ToString(ct).Replace("-", "").Remove(0, 3);
                    }
                    else
                    {
                        second2 += 1;
                        second2 += BitConverter.ToString(ct).Replace("-", "").Remove(0, 3);
                    }
                    byte second = byte.Parse(second2, System.Globalization.NumberStyles.HexNumber);
                    Color c;
                    ListViewNode.SubItems[ListViewNode.SubItems.Count - 1].Text = getType(out c, first, second);
                    co = c;
                    ListViewNode.SubItems[ListViewNode.SubItems.Count - 1].Text += " (" + BitConverter.ToString(ct).Replace("-", "") + ")";
                }
            }
            public byte CollisionType_
            {
                get { return (byte)(CollisionType & 31); }
                set
                {
                    if (value > 31)
                    {
                        throw new Exception("The value can be maximal 31. It is 5 bits.");
                    }
                    ushort a = 0;
                    a |= (ushort)(value & 31);
                    a |= (ushort)(Collisioneffect << 5);
                    a |= (ushort)(Shadoweffect << 8);
                    a |= (ushort)(Intesity << 11);
                    a |= (ushort)(Basiceffect << 13);
                    CollisionType = a;
                }
            }
            public byte Basiceffect
            {
                get { return (byte)(CollisionType >> 13 & 7); }
                set
                {
                    if (value > 7)
                    {
                        throw new Exception("The value can be maximal 7. It is 3 bits.");
                    }
                    ushort a = 0;
                    a |= (ushort)(CollisionType_ & 31);
                    a |= (ushort)(Collisioneffect << 5);
                    a |= (ushort)(Shadoweffect << 8);
                    a |= (ushort)(Intesity << 11);
                    a |= (ushort)(value << 13);
                    CollisionType = a;
                }
            }
            public byte Collisioneffect
            {
                get { return (byte)(CollisionType >> 5 & 7); }
                set
                {
                    if (value > 7)
                    {
                        throw new Exception("The value can be maximal 7. It is 3 bits.");
                    }
                    ushort a = 0;
                    a |= (ushort)(CollisionType_ & 31);
                    a |= (ushort)(value << 5);
                    a |= (ushort)(Shadoweffect << 8);
                    a |= (ushort)(Intesity << 11);
                    a |= (ushort)(Basiceffect << 13);
                    CollisionType = a;
                }
            }
            public byte Shadoweffect
            {
                get { return (byte)(CollisionType >> 8 & 7); }
                set
                {
                    if (value > 7)
                    {
                        throw new Exception("The value can be maximal 7. It is 3 bits.");
                    }
                    ushort a = 0;
                    a |= (ushort)(CollisionType_ & 31);
                    a |= (ushort)(Collisioneffect << 5);
                    a |= (ushort)(value << 8);
                    a |= (ushort)(Intesity << 11);
                    a |= (ushort)(Basiceffect << 13);
                    CollisionType = a;
                }
            }
            public byte Intesity
            {
                get { return (byte)(CollisionType >> 11 & 3); }
                set
                {
                    if (value > 3)
                    {
                        throw new Exception("The value can be maximal 3. It is 2 bits.");
                    }
                    ushort a = 0;
                    a |= (ushort)(CollisionType_ & 31);
                    a |= (ushort)(Collisioneffect << 5);
                    a |= (ushort)(Shadoweffect << 8);
                    a |= (ushort)(value << 11);
                    a |= (ushort)(Basiceffect << 13);
                    CollisionType = a;
                }
            }
            public enum basicType0
            {
                Normal_Road,
                Dirt_Road,
                Sand,
                Slippery_Road,
                Wood_Road,
                Snow_Road,
                Metal_Grid_or_ChainLink_Road,
                Another_Normal_Road
            };

            float x1;
            [Category("Position 1"), DefaultValue(0), DisplayName("X"), Description("The X position.")]
            public float X1
            {
                get { return x1; }
            }
            float y1;
            [Category("Position 1"), DefaultValue(0), DisplayName("Y"), Description("The Y position.")]
            public float Y1
            {
                get { return y1; }
            }
            float z1;
            [Category("Position 1"), DefaultValue(0), DisplayName("Z"), Description("The Z position.")]
            public float Z1
            {
                get { return z1; }
            }
            float x2;
            [Category("Position 2"), DefaultValue(0), DisplayName("X"), Description("The X position.")]
            public float X2
            {
                get { return x2; }
            }
            float y2;
            [Category("Position 2"), DefaultValue(0), DisplayName("Y"), Description("The Y position.")]
            public float Y2
            {
                get { return y2; }
            }
            float z2;
            [Category("Position 2"), DefaultValue(0), DisplayName("Z"), Description("The Z position.")]
            public float Z2
            {
                get { return z2; }
            }
            float x3;
            [Category("Position 3"), DefaultValue(0), DisplayName("X"), Description("The X position.")]
            public float X3
            {
                get { return x3; }
            }
            float y3;
            [Category("Position 3"), DefaultValue(0), DisplayName("Y"), Description("The Y position.")]
            public float Y3
            {
                get { return y3; }
            }
            float z3;
            [Category("Position 3"), DefaultValue(0), DisplayName("Z"), Description("The Z position.")]
            public float Z3
            {
                get { return z3; }
            }
            public void SetPositions(Vector3 a, Vector3 b, Vector3 c)
            {
                x1 = a.X;
                x2 = b.X;
                x3 = c.X;
                y1 = a.Y;
                y2 = b.Y;
                y3 = c.Y;
                z1 = a.Z;
                z2 = b.Z;
                z3 = c.Z;
            }
        }
        private static byte[] stringtobyte(string a)
        {
            byte[] buffer;
            int discarded;
            buffer = Utility.HexEncoding.GetBytes(a, out discarded);
            return buffer;
        }
        public class UInt16HexTypeConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == typeof(string))
                {
                    return true;
                }
                else
                {
                    return base.CanConvertFrom(context, sourceType);
                }
            }

            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == typeof(string))
                {
                    return true;
                }
                else
                {
                    return base.CanConvertTo(context, destinationType);
                }
            }

            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (destinationType == typeof(string) && value.GetType() == typeof(UInt16))
                {
                    string t = string.Format("{0:X4}", value);
                    for (int i = 0; i < 4 - t.Length; i++)
                    {
                        t += "0";
                    }
                    return t;
                }
                else
                {
                    return base.ConvertTo(context, culture, value, destinationType);
                }
            }

            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value.GetType() == typeof(string))
                {
                    string input = (string)value;

                    if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                    {
                        input = input.Substring(2);
                    }

                    return UInt16.Parse(input, System.Globalization.NumberStyles.HexNumber, culture);
                }
                else
                {
                    return base.ConvertFrom(context, culture, value);
                }
            }
        }
        int m_x = 0;
        int m_y = 0;
        uint col = 0;
        private void simpleOpenGlControl1_MouseMove(object sender, MouseEventArgs e)
        {
            m_x = e.X;
            m_y = e.Y;
            //simpleOpenGlControl1.Refresh();
            //RenderFunc1();
        }

        private void simpleOpenGlControl1_MouseUp(object sender, MouseEventArgs e)
        {
            //MessageBox.Show(col.ToString());
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && openFileDialog1.FileName.Length > 0)
            {
                /*HelixToolkit.ObjReader r = new HelixToolkit.ObjReader();
                r.Read(openFileDialog1.FileName);*/
                List<int> Materialu = new List<int>();
                List<string> names = new List<string>();
                Stream fs = File.OpenRead(openFileDialog1.FileName);
                StreamReader sr = new StreamReader(fs);

                string curmaterial = "";
                CultureInfo usahax = new CultureInfo("en-US");

                string curline;
                while ((curline = sr.ReadLine()) != null)
                {
                    curline = curline.Trim();

                    // skip empty lines and comments
                    if (curline.Length < 1) continue;
                    if (curline[0] == '#') continue;

                    string[] parts = curline.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length < 1) continue;
                    int face = 0;
                    switch (parts[0])
                    {
                        case "mtllib": // material lib file
                            {
                                //string filename = curline.Substring(parts[0].Length + 1).Trim();
                                //OBJ_LoadMTL(m_ModelPath + filename);
                            }
                            break;

                        case "usemtl": // material name
                            if (parts.Length < 2) continue;
                            curmaterial = parts[1];
                            if (!names.Contains(curmaterial))
                            {
                                names.Add(curmaterial);
                            }
                            break;

                        case "v": // vertex
                            {
                                //if (parts.Length < 4) continue;
                                //float x = float.Parse(parts[1], usahax);
                                //float y = float.Parse(parts[2], usahax);
                                //float z = float.Parse(parts[3], usahax);
                                //float w = 1f; //(parts.Length < 5) ? 1f : float.Parse(parts[4], usahax);

                                //m_Vertices.Add(new Vector4(x, y, z, w));
                            }
                            break;

                        case "vt": // texcoord
                            {
                                //if (parts.Length < 2) continue;
                                //float s = float.Parse(parts[1], usahax);
                                //float t = (parts.Length < 3) ? 0f : float.Parse(parts[2], usahax);

                                //m_TexCoords.Add(new Vector2(s, t));
                            }
                            break;

                        case "vn": // normal
                            {
                                //if (parts.Length < 4) continue;
                                //float x = float.Parse(parts[1], usahax);
                                //float y = float.Parse(parts[2], usahax);
                                //float z = float.Parse(parts[3], usahax);

                                //Vector3 vec = new Vector3(x, y, z);
                                //vec.Normalize();
                                //m_Normals.Add(vec);
                            }
                            break;

                        case "f": // face
                            {
                                /*if (parts.Length < 4) continue;
                                int nvtx = parts.Length - 1;

                                MaterialDef mat = (MaterialDef)m_Materials[curmaterial];
                                FaceDef face = new FaceDef();
                                face.m_MatName = curmaterial;
                                face.m_VtxIndices = new int[nvtx];
                                face.m_TxcIndices = new int[nvtx];
                                face.m_NrmIndices = new int[nvtx];

                                for (int i = 0; i < nvtx; i++)
                                {
                                    string vtx = parts[i + 1];
                                    string[] idxs = vtx.Split(new char[] { '/' });

                                    face.m_VtxIndices[i] = int.Parse(idxs[0]) - 1;
                                    face.m_TxcIndices[i] = (mat.m_HasTextures && idxs.Length >= 2 && idxs[1].Length > 0)
                                        ? (int.Parse(idxs[1]) - 1) : -1;
                                    face.m_NrmIndices[i] = (idxs.Length >= 3) ? (int.Parse(idxs[2]) - 1) : -1;
                                }

                                mat.m_Faces.Add(face);*/
                                Materialu.Add(names.IndexOf(curmaterial));
                            }
                            break;
                    }
                }

                sr.Close();

                kclType t = new kclType(names.ToArray());
                t.DialogResult = DialogResult.None;
                t.ShowDialog();
                while (t.DialogResult != DialogResult.OK) ;
                Dictionary<string, ushort> Mapping;
                Mapping = t.Mapping;

                for (int j = 0; j < k.Planes.Items.Count; j++)
                {
                    k.Planes.Items[j].Type = stringtobyte(string.Format("{0:X4}", Mapping[names[Materialu[j]]]));
                    byte[] ct = stringtobyte(string.Format("{0:x4}", Mapping[names[Materialu[j]]]));
                    byte first = ct[0];
                    string second2 = "";
                    if (BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "0" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "2" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "4" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "6" ||
                        BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "8" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "A" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "C" || BitConverter.ToString(ct).Replace("-", "").Remove(0, 2).Remove(1, 1) == "E")
                    {
                        second2 += 0;
                        second2 += BitConverter.ToString(ct).Replace("-", "").Remove(0, 3);
                    }
                    else
                    {
                        second2 += 1;
                        second2 += BitConverter.ToString(ct).Replace("-", "").Remove(0, 3);
                    }
                    byte second = byte.Parse(second2, System.Globalization.NumberStyles.HexNumber);
                    Color c;
                    listView3.Items[j].SubItems[listView3.Items[j].SubItems.Count - 1].Text = getType(out c, first, second);
                    listView3.Items[j].SubItems[listView3.Items[j].SubItems.Count - 1].Text += " (" + BitConverter.ToString(ct).Replace("-", "") + ")";
                    colors[j] = c;
                    try
                    {
                        kclEditorControl1.Planes[j].MarkerColor = c;
                    }
                    catch { }
                }
            }
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            List<VerteX> Verci = new List<VerteX>();
            List<NormaL> N = new List<NormaL>();
            for (int i = 0; i < k.Planes.Items.Count; i++)
            {
                int c = containsVt(k.Vertex.Items[k.Planes.Items[i].VertexIndex], Verci);
                if (c == -1)
                {
                    Verci.Add(k.Vertex.Items[k.Planes.Items[i].VertexIndex]);
                    k.Planes.Items[i].VertexIndex = (short)(Verci.Count - 1);
                }
                else
                {
                    k.Planes.Items[i].VertexIndex = (short)c;
                }
                c = containsN(k.Normals.Items[k.Planes.Items[i].NormalIndex], N);
                if (c == -1)
                {
                    N.Add(k.Normals.Items[k.Planes.Items[i].NormalIndex]);
                    k.Planes.Items[i].NormalIndex = (short)(N.Count - 1);
                }
                else
                {
                    k.Planes.Items[i].NormalIndex = (short)c;
                }
                c = containsN(k.Normals.Items[k.Planes.Items[i].NormalAIndex], N);
                if (c == -1)
                {
                    N.Add(k.Normals.Items[k.Planes.Items[i].NormalAIndex]);
                    k.Planes.Items[i].NormalAIndex = (short)(N.Count - 1);
                }
                else
                {
                    k.Planes.Items[i].NormalAIndex = (short)c;
                }
                c = containsN(k.Normals.Items[k.Planes.Items[i].NormalBIndex], N);
                if (c == -1)
                {
                    N.Add(k.Normals.Items[k.Planes.Items[i].NormalBIndex]);
                    k.Planes.Items[i].NormalBIndex = (short)(N.Count - 1);
                }
                else
                {
                    k.Planes.Items[i].NormalBIndex = (short)c;
                }
                c = containsN(k.Normals.Items[k.Planes.Items[i].NormalCIndex], N);
                if (c == -1)
                {
                    N.Add(k.Normals.Items[k.Planes.Items[i].NormalCIndex]);
                    k.Planes.Items[i].NormalCIndex = (short)(N.Count - 1);
                }
                else
                {
                    k.Planes.Items[i].NormalCIndex = (short)c;
                }
            }
            k.Vertex.Items = Verci;
            k.Normals.Items = N;

            toolStripButton1.PerformClick();
            this.Close();
        }

        public int containsVt(VerteX a, List<VerteX> b)
        {
            for (int i = 0; i < b.Count; i++)
            {
                if (b[i].X == a.X && b[i].Y == a.Y && b[i].Z == a.Z)
                {
                    return i;
                }
            }
            return -1;
        }
        public int containsN(NormaL a, List<NormaL> b)
        {
            for (int i = 0; i < b.Count; i++)
            {
                if (b[i].X == a.X && b[i].Y == a.Y && b[i].Z == a.Z)
                {
                    return i;
                }
            }
            return -1;
        }
    }
}
